﻿package zf.data.geom.plan
{
	import flash.display.Sprite;
	import flash.geom.Point;

	import zf.data.geom.Beeline;
	import zf.data.geom.Formula;

	/**
	 * 圆类，你可以使用静态方法Circle.creatCircle()方法快速创建一个圆
	 * 圆方程：x^2 + y^2 = r^2 
	 * 圆一般方程(dx和dy是圆心点坐标): (x - dx)^2 + (y - dy)^2 = r^2;
	 * @author Mike.zhang
	 * @langversion 3.0 
	 * @playerversion Flash 9 
	 * 
	 */
	public class Circle
	{
		private var _center:Point;
		private var _radii:Number;

		/**
		 * 创建圆  
		 * 
		 */
		public function Circle ()
		{
		}
		/**
		 * 圆半径 
		 * @return 半径长度
		 * 
		 */
		public function get radii ():Number
		{
			return _radii;
		}

		public function set radii (v:Number):void
		{
			_radii=v;
		}

		/**
		 * 圆心所在的点 
		 * @return Point
		 * 
		 */
		public function get center ():Point
		{
			return _center;
		}

		public function set center (v:Point):void
		{
			_center=v;
		}
		/**
		 * 依据中心点和半径创建一个圆 
		 * @param c 圆心
		 * @param r 圆半径
		 * @return 圆
		 * 
		 */
		public static  function creatCircle (c:Point,r:Number):Circle
		{
			var myc:Circle=new Circle  ;
			myc.center=c;
			myc.radii=r;
			return myc;
		}
		/**
		 * 检测两圆是否相撞 
		 * @param c 待检测的圆
		 * @return 相撞返回true
		 * 
		 */
		public function hitCircle (c:Circle):Boolean
		{
			return Formula.distance(c.center.x,c.center.y,center.x,center.y) <= c.radii + radii;
		}
		/**
		 * 检测点是否在圆上 
		 * @param p 待检测的点
		 * @return 在圆上返回true
		 * 
		 */
		public function hitPoint (p:Point):Boolean
		{
			//return Formula.distance(p.x,p.y,center.x,center.y)<=radii;
			var px:Number=p.x - center.x;
			var py:Number=p.y - center.y;
			return px * px + py * py <= radii * radii;
		}
		/**
		 * 检测线与圆的相撞情况 
		 * @param l 待检测的线，必须实现ILine接口
		 * @return 相撞返回true
		 * 
		 * @see zf.data.geom.Beeline
		 * 
		 */
		public function hitLine (l:Beeline):Boolean
		{
			return l.pointDistance(center) <= radii;
		}
		/**
		 * 获取直线l和圆的相交点，如果没有相交返回为null，如有有相交，会有1-2个交点，返回的数组中元素为一个交点 
		 * @param l Beeline 直线
		 * @return 数组，数组元素为交点Point
		 * 
		 * @see zf.data.geom.Beeline
		 */
		/*public function getHitLinePoint(l:Beeline):Array
		{
		//代入法
		var A:Number=l.k*l.k+1;
		var B:Number=2*l.k*l.b-2*l.k*l.b-2*center.x;
		var C:Number=center.x*center.x-radii*radii+Math.pow(l.b-center.y,2);
		var num:Number=B*B-4*A*C;
		if(num>=0)
		{
		var x1:Number,y1:Number;
		var arr:Array=new Array
		if(num==0)
		{
		x1=-B*0.5/A;
		y1=l.k*x1+l.b;
		arr.push(new Point(x1,y1));
		return arr;
		}else
		{
		var x2:Number,y2:Number;
		num=Math.sqrt(num);
		x1=(-B+num)*0.5/A;
		y1=l.k*x1+l.b;
		x2=(-B-num)*0.5/A;
		y2=l.k*x2+l.b;
		arr.push(new Point(x1,y1));
		arr.push(new Point(x2,y2));
		return arr;
		}
		}
		return null;
		}*/
		public function getHitLinePoint (l:Beeline):Array
		{
			//根据圆心的平移计算出平移后线的方程
			var newL:Beeline=l.move(center.x,center.y);

			//利用平移后线的方程与圆的标准方程进行相交判断
			var A:Number=1 + newL.k * newL.k;
			var B:Number=2 * newL.k * newL.b;
			var C:Number=newL.b * newL.b - radii * radii;

			var num:Number=B * B - 4 * A * C;

			//计算出的交点必须再平移回去
			if (num >= 0)
			{
				var x1:Number,y1:Number;
				var arr:Array=new Array  ;
				if (num == 0)
				{
					x1=- B * 0.5 / A;
					y1=newL.k * x1 + newL.b;
					arr.push (new Point(x1 + center.x,y1 + center.y));
					return arr;
				}
				else
				{
					var x2:Number,y2:Number;
					num=Math.sqrt(num);
					x1=- B + num * 0.5 / A;
					y1=newL.k * x1 + newL.b;
					x2=- B - num * 0.5 / A;
					y2=newL.k * x2 + newL.b;
					arr.push (new Point(x1 + center.x,y1 + center.y));
					arr.push (new Point(x2 + center.x,y2 + center.y));
					return arr;
				}
			}
			return null;
		}
		/**
		 * 绘制圆
		 * 在使用前需要设置填充及线条信息。 
		 * @param target 一个可以绘制的对象。将在这个对象上绘制图形。请注意，它必须有graphics，一般情况下，它必须是flash.display.Sprite类及其子类
		 * 
		 */
		public function draw (target:Sprite):void
		{
			//var dx:Number=x+radii;
			//var dy:Number=y+radii;
			target.graphics.drawCircle (center.x,center.y,radii);
		}
		/**
		 * 返回圆的描述信息 
		 * @return 格式[center=(dx,dy) radii=r]
		 * 
		 */
		public function toString ():String
		{
			return "[center=" + center + " radii=" + radii + "]";
		}

	}
}